﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using UtopianGame.graphics;
using Microsoft.Xna.Framework.Content;
using GameDataLibrary;

namespace UtopianGame
{
    static class GlobalDataHolder
    {
        public static List<GraphicalObject> graphicalObjectList;
        public static Policy[] policyArray;
        public static Infrastructure[] infrastructureArray;
        public static StatusEffect[] statusEffectArray;
        public static RandomEvent[] randomEventArray;
        public static SpriteFont baseFont;
        public static ContentManager cManager;
        public static String randomEventName;
        public static String randomEventDescription;

        public static int currentlySelectedRegion;

        public static bool isGameOver;

        public static void init(ContentManager cm)
        {
            cManager = cm;
            isGameOver = false;
            graphicalObjectList = new List<GraphicalObject>();
            baseFont = cm.Load<SpriteFont>("BaseFont");
            PolicyData[] policyDataArray = cm.Load<PolicyData[]>("policies");
            policyArray = loadPolicyArray(policyDataArray);
            StatusEffectData[] statusEffectDataArray = cm.Load<StatusEffectData[]>("statusEffects");
            statusEffectArray = loadStatusEffectArray(statusEffectDataArray);
            InfrastructureData[] infrastructureDataArray = cm.Load<InfrastructureData[]>("infrastructures");
            infrastructureArray = loadInfrastructureArray(infrastructureDataArray);
            RandomEventData[] RandomEventDataArray = cm.Load<RandomEventData[]>("randomEvents");
            randomEventArray = loadRandomEventArray(RandomEventDataArray);

            randomEventName = "";
            randomEventDescription = "";

            currentlySelectedRegion = 1;
            
        }

        private static Policy[] loadPolicyArray(PolicyData[] policyDataArray)
        {
            Policy[] newArray = new Policy[policyDataArray.Length];
            for (int i = 0; i < newArray.Length; i++)
            {
                newArray[i] = new Policy(policyDataArray[i]);
            }
            return newArray;
        }

        private static Infrastructure[] loadInfrastructureArray(InfrastructureData[] infrastructureDataArray)
        {
            Infrastructure[] newArray = new Infrastructure[infrastructureDataArray.Length];
            for (int i = 0; i < newArray.Length; i++)
            {
                newArray[i] = new Infrastructure(infrastructureDataArray[i]);
            }
            return newArray;
        }

        private static StatusEffect[] loadStatusEffectArray(StatusEffectData[] StatusEffectDataArray)
        {
            StatusEffect[] newArray = new StatusEffect[StatusEffectDataArray.Length];
            for (int i = 0; i < newArray.Length; i++)
            {
                newArray[i] = new StatusEffect(StatusEffectDataArray[i]);
            }
            return newArray;
        }

        private static RandomEvent[] loadRandomEventArray(RandomEventData[] RandomEventDataArray)
        {
            RandomEvent[] newArray = new RandomEvent[RandomEventDataArray.Length];
            for (int i = 0; i < newArray.Length; i++)
            {
                newArray[i] = new RandomEvent(RandomEventDataArray[i]);
            }
            return newArray;
        }

        /// <summary>
        /// This is used to add an instance of GraphicalObject to the game.
        /// </summary>
        /// <param name="obj">A pointer of the object to add.</param>
        /// <param name="xCoord">The x coordinate on the window of the object.</param>
        /// <param name="yCoord">The y coordinate on the window of the object.</param>
        public static GraphicalObject addGraphicalObject(GraphicalObject obj, int xCoord = 0, int yCoord = 0, int depth = 0)
        {
            int currentIndex = 0;

            if (graphicalObjectList.Count >= 1)
            {
                List<GraphicalObject>.Enumerator graphicalObjectEnumerator = graphicalObjectList.GetEnumerator();
                
                //Note on the below While() statement:
                //graphicalObjectEnumerator.MoveNext() will return false when it exits
                //the last element of the list.
                while (graphicalObjectEnumerator.MoveNext())
                {
                    if (graphicalObjectEnumerator.Current.getDepth() > depth)
                    {
                        break;
                    }

                    currentIndex++;
                }
            }

            graphicalObjectList.Insert(currentIndex, obj);
            obj.setCoords(xCoord, yCoord);
            obj.setDepth(depth);
            return obj;
        }

        //Removes an object and all of its subObjects.
        public static void removeGraphicalObject(GraphicalObject objToRemove)
        {
            //finds and removes all of objToRemove's subObjects
            while(objToRemove.getSubObjectList().Count > 0)
            {
                GraphicalObject subObj = objToRemove.getSubObjectList().First();
                removeGraphicalObject(subObj);
            }
            //removes the object from graphicalObjectList, and its parent's
            //subObjectList.
            graphicalObjectList.Remove(objToRemove);
            objToRemove.removed();  //calls any special behavior that happens when object is removed.
            GraphicalObject parentObj = objToRemove.getParentObject();
            if (parentObj != null)
            {
                parentObj.removeFromSubObjectList(objToRemove);
            }
        }

        public static void makeActive(GraphicalObject newActiveObject)
        {
            List<GraphicalObject>.Enumerator graphicalObjectEnumerator = graphicalObjectList.GetEnumerator();
                
                //Note on the below While() statement:
                //graphicalObjectEnumerator.MoveNext() will return false when it exits
                //the last element of the list.
            while (graphicalObjectEnumerator.MoveNext())
            {
                GraphicalObject currentObj = graphicalObjectEnumerator.Current;
                if (currentObj == newActiveObject || newActiveObject.getSubObjectList().Contains(currentObj))
                {
                    currentObj.setIsActive(true);
                }
                else
                {
                    currentObj.setIsActive(false);
                }
            }
        }

        public static void  makeEverythingActive()
        {
            List<GraphicalObject>.Enumerator graphicalObjectEnumerator = graphicalObjectList.GetEnumerator();

            //Note on the below While() statement:
            //graphicalObjectEnumerator.MoveNext() will return false when it exits
            //the last element of the list.
            while (graphicalObjectEnumerator.MoveNext())
            {
                GraphicalObject currentObj = graphicalObjectEnumerator.Current;
                currentObj.setIsActive(true);
            }
        }
    }
}
